home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / c-tools / mui2c / id.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-22  |  10.8 KB  |  393 lines

  1. /***** =id.c
  2.  *
  3.  *  $VER: id.c 1.003 (22 Jun 1996)
  4.  *
  5.  *        © 1996 jasonb
  6.  *
  7.  *  PROGRAMNAME:
  8.  *      id.c
  9.  *
  10.  ***** --background--
  11.  *      These are the housekeeping functions that keep track of declared methods
  12.  *      and attributes, and writes the public and private header files.
  13.  *
  14.  *      All data is currently stored in fixed size arrays, rather than dynamically.
  15.  *      I did this because, as this is a preprocessor, I wanted to maximize speed
  16.  *      (although perhaps with all the I/O going on it doesn't make much difference),
  17.  *      and because the number of IDs in any given class should be quite limited anyway.
  18.  *      I've set the limit to 256, but that could easily be raised if the need arose.
  19.  *      All limits are #define'd below.
  20.  *
  21.  *      All strings are hardwired, also. If someone wishes to localize this program,
  22.  *      feel free.
  23.  *
  24.  *****
  25.  *
  26.  *  $HISTORY:
  27.  *
  28.  *  22 Jun 1996 : 001.003 : Added ATT_TRAILER_SMALL.
  29.  *  21 Jun 1996 : 001.002 : Added automatic data setup code back in, took care of extra special cases, added Method* keyword.
  30.  *  20 Jun 1996 : 001.001 : Removed automatic data setup from all methods and superclass calls from OM_GET and OM_SET.
  31.  *  19 Jun 1996 : 001.000 : Initial release.
  32.  */
  33.  
  34.  
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <time.h>
  40.  
  41. #include "id.h"
  42.  
  43. #define NOOFIDS                 256
  44. #define CLASSNAMELENGTH         64
  45. #define SUPERCLASSNAMELENGTH    64
  46. #define DATANAMELENGTH          64
  47. #define NAMELENGTH              64
  48.  
  49. #define TRUE    1
  50. #define FALSE   0
  51.  
  52. typedef struct {
  53.     char    name[NAMELENGTH];
  54.     char    type;
  55.     long    value;
  56. } ID;
  57.  
  58. ID      ids[NOOFIDS];
  59. long    idcnt=0, mthcnt=0, attcnt=0;
  60. char    clsname[CLASSNAMELENGTH];
  61. char    superclsname[SUPERCLASSNAMELENGTH];
  62. char    dataname[DATANAMELENGTH];
  63. char    methodbase[CLASSNAMELENGTH+6];
  64. char    attributebase[CLASSNAMELENGTH+6];
  65.  
  66. char    *messages[] = {
  67.     // GET_HEADER -- header for an OM_GET method
  68.     "static SAVEDS ULONG %s_OM_GET(struct IClass *cl, Object *obj, Msg msg)\n",
  69.  
  70.     // GET_VARS -- variable declarations for an OM_GET method
  71.     "\tULONG *store = ((struct opGet *) msg)->opg_Storage;\n"
  72.     "\tULONG tag = ((struct opGet *) msg)->opg_AttrID;\n",
  73.  
  74.     // SET_HEADER -- header for an OM_SET method
  75.     "static SAVEDS ULONG %s_OM_SET(struct IClass *cl, Object *obj, Msg msg)\n",
  76.  
  77.     // SET_VARS -- variable declarations for an OM_SET method
  78.     "\tstruct TagItem *tags, *tag;\n",
  79.  
  80.     // MTH_HEADER -- header for a general method
  81.     "static SAVEDS ULONG %s_%s(struct IClass *cl, Object *obj, Msg msg)\n",
  82.  
  83.     // MTH_VARS -- variable declarations for a general method
  84.     "{\n\t%s *data = INST_DATA(cl, obj);\n\n",
  85.  
  86.     // MTH_VARS_SMALL -- variable declarations for a special cutdown method
  87.     "{\n",
  88.  
  89.     // MTH_VARS_SUPER_GET_OBJ -- variable declarations for OM_NEW method
  90.     "{\n\t%s *data;\n\n"
  91.     "\tif (!(obj = (Object *) DoSuperMethodA(cl, obj, msg)))\n"
  92.     "\t\treturn (0);\n\n"
  93.     "\tdata = INST_DATA(cl, obj);\n\t{ /* Begin user code */\n\n",
  94.  
  95.     // MTH_VARS_SUPER_CHECK -- variable declarations for MUIM_Setup method
  96.     "{\n\t%s *data = INST_DATA(cl, obj);\n\n"
  97.     "\tif (!DoSuperMethodA(cl,obj,msg))\n"
  98.     "\t\treturn (FALSE);\n\t{ /* Begin user code */\n\n",
  99.  
  100.     // MTH_VARS_SUPER -- variable declarations including unchecked call to superclass
  101.     "{\n\t%s *data = INST_DATA(cl, obj);\n\n"
  102.     "\tDoSuperMethodA(cl, obj, msg);\n\t{ /* Begin user code */\n\n",
  103.  
  104.     // GET_DEFS_TRAILER -- end of attribute definitions for an OM_GET method
  105.     "}\n",
  106.  
  107.     // GET_TRAILER -- end code for an OM_GET method
  108.     "\treturn (DoSuperMethodA(cl, obj, msg));\n}\n",
  109.  
  110.     // SET_DEFS_TRAILER -- end of attribute definitions for an OM_SET method
  111.     "  }\n\t}\n",
  112.  
  113.     // SET_TRAILER -- end code for an OM_SET method
  114.     "\treturn (DoSuperMethodA(cl, obj, msg));\n}\n",
  115.  
  116.     // MTH_TRAILER -- end code for a general method
  117.     "\n\treturn (DoSuperMethodA(cl, obj, msg));\n}\n",
  118.  
  119.     // MTH_TRAILER_SMALL -- end code for a special cutdown method
  120.     "\n}\n",
  121.  
  122.     // MTH_TRAILER_RET_OBJ -- end code for returning an object
  123.     "\n\t} /* End user code */\n\treturn ((ULONG) obj);\n}\n",
  124.  
  125.     // MTH_TRAILER_RET_ZERO -- end code for returning a zero
  126.     "\n\t} /* End user code */\n\treturn (0);\n}\n",
  127.  
  128.     // MTH_TRAILER_RET_TRUE -- end code for returning a true
  129.     "\n\t} /* End user code */\n\treturn (TRUE);\n}\n",
  130.  
  131.     // GET_ATT_TRAILER -- end code for an individual attribute defn in an OM_GET method
  132.     "\n\t\t\treturn (TRUE);\n\t\t}\n",
  133.  
  134.     // SET_ATT_TRAILER -- end code for an individual attribute defn in an OM_SET method
  135.     "\n\t\t\tbreak;\n\t\t}\n",
  136.  
  137.     // ATT_TRAILER_SMALL -- end code for an individual attribute defn without return or break
  138.     "\n\t\t}\n",
  139.  
  140.     // INGETMETH -- beginning of attribute defns for an OM_GET method
  141.     "\tswitch (tag) {\n",
  142.  
  143.     // INSETMETH -- beginning of attribute defns for an OM_SET method
  144.     "\tfor (tags = ((struct opSet *) msg)->ops_AttrList; tag = NextTagItem(&tags);) {\n"
  145.     "\t  switch (tag->ti_Tag) {\n",
  146.  
  147.     // CASE -- attribute definition code
  148.     "case %s:",
  149.  
  150.     // DISPATCH_HEADER -- header for dispatcher
  151.     "static SAVEDS ASM ULONG %s_Dispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)\n{\n"
  152.     "\tswitch (msg->MethodID) {\n",
  153.  
  154.     // DISPATCH_CASE -- code for an individual method in the dispatcher
  155.     "\t\tcase %s: return (%s_%s(cl, obj, (APTR) msg));\n",
  156.  
  157.     // DISPATCH_TRAILER -- end of dispatcher
  158.     "\t}\n\n\treturn (DoSuperMethodA(cl, obj, msg));\n}\n\n",
  159.  
  160.     // CONSTRUCTOR_HEADER -- header for constructor function
  161.     "struct MUI_CustomClass *%s_Create(void)%s",
  162.  
  163.     // CONSTRUCTOR_BODY -- code for constructure function
  164.     "\treturn (MUI_CreateCustomClass(NULL, %s, NULL, sizeof(%s), %s_Dispatcher));\n}\n",
  165.  
  166.     // ERROPENR
  167.     "Error: Couldn't open %s for reading.\n",
  168.  
  169.     // ERROPENW
  170.     "Error: Couldn't open %s for writing.\n",
  171.  
  172.     // HEADER -- header for files
  173.     "/*\n * %s file for class %s.\n"
  174.     " * Automatically generated on %s"
  175.     " *\n */\n\n",
  176.  
  177.     // DEFINES -- #defines for cross-compiler compatibility
  178.     "#ifdef _DCC\n"
  179.     "#define REG(x) __ ## x\n"
  180.     "#define ASM\n"
  181.     "#define SAVEDS __geta4\n"
  182.     "#else\n"
  183.     "#define REG(x) register __ ## x\n\n"
  184.     "#if defined __MAXON__ || defined __GNUC__\n"
  185.     "#define ASM\n"
  186.     "#define SAVEDS\n"
  187.     "#else\n"
  188.     "#define ASM\t__asm\n"
  189.     "#define SAVEDS __saveds\n"
  190.     "#endif\n#endif\n\n"
  191.     "#define Super() DoSuperMethodA(cl, obj, msg)\n"
  192.     "#define GetData() INST_DATA(cl, obj)\n\n"
  193. };
  194.  
  195. struct {
  196.     char *msg;
  197.     unsigned long vars, trailer;
  198. } special_cases[] = {
  199.     "OM_NEW", MTH_VARS_SUPER_GET_OBJ, MTH_TRAILER_RET_OBJ,
  200.     "MUIM_AskMinMax", MTH_VARS_SUPER, MTH_TRAILER_RET_ZERO,
  201.     "MUIM_Setup", MTH_VARS_SUPER_CHECK, MTH_TRAILER_RET_TRUE,
  202.     "MUIM_Show", MTH_VARS_SUPER, MTH_TRAILER_RET_TRUE,
  203.     "MUIM_Draw", MTH_VARS_SUPER, MTH_TRAILER_RET_ZERO,
  204.     NULL, 0, 0
  205. };
  206.  
  207. void CheckSpecialCases(char *name, unsigned long *vars, unsigned long *trailer)
  208. {
  209.     int i;
  210.  
  211.     for (i=0; special_cases[i].msg; i++)
  212.         if (strcmp(name, special_cases[i].msg) == 0)
  213.             break;
  214.  
  215.     if (special_cases[i].msg){
  216.         *vars = special_cases[i].vars;
  217.         *trailer = special_cases[i].trailer;
  218.     } else {
  219.         *vars = MTH_VARS;
  220.         *trailer = MTH_TRAILER;
  221.     }
  222. }
  223.  
  224. void SetClassName(char *name)
  225. {
  226.     if (strlen(name) > CLASSNAMELENGTH){
  227.         printf("Error: Name %s too long. Must be %d characters or less.\n", name, CLASSNAMELENGTH);
  228.         exit(1);
  229.     }
  230.  
  231.     strcpy(clsname, name);
  232.  
  233.     sprintf(methodbase,"MUIM_%s_",clsname);
  234.     sprintf(attributebase,"MUIA_%s_",clsname);
  235. }
  236.  
  237. void SetSuperClassName(char *name)
  238. {
  239.     if (strlen(name) > SUPERCLASSNAMELENGTH){
  240.         printf("Error: Name %s too long. Must be %d characters or less.\n", name, SUPERCLASSNAMELENGTH);
  241.         exit(1);
  242.     }
  243.  
  244.     strcpy(superclsname, name);
  245. }
  246.  
  247. void SetDataName(char *name)
  248. {
  249.     if (strlen(name) > DATANAMELENGTH){
  250.         printf("Error: Name %s too long. Must be %d characters or less.\n", name, DATANAMELENGTH);
  251.         exit(1);
  252.     }
  253.  
  254.     strcpy(dataname, name);
  255. }
  256.  
  257. void Add(char *name, char type)
  258. {
  259.     long i,value=0;
  260.     char done = FALSE;
  261.  
  262.     if (strlen(name) > NAMELENGTH){
  263.         printf("Error: Name %s too long. Must be %d characters or less.\n", name, NAMELENGTH);
  264.         exit(1);
  265.     }
  266.  
  267.     if ((type & METHOD) && (type & ATTRIBUTE)){
  268.         printf("Error: Name %s given as both METHOD and ATTRIBUTE.\n", name);
  269.         exit(1);
  270.     }
  271.  
  272.     if (type & METHOD)
  273.         // Does this look like a local method?
  274.         if (strncmp(methodbase, name, strlen(methodbase)) == 0)
  275.             value = mthcnt++;
  276.         else // No, must be inherited
  277.             value = 0;
  278.     else if (type & ATTRIBUTE)
  279.         // Does this look like a local attribute?
  280.         if (strncmp(attributebase, name, strlen(attributebase)) == 0)
  281.             value = attcnt++;
  282.         else // No, must be inherited
  283.             value = 0;
  284.     else {
  285.         printf("Error: Name %s must be one of METHOD or ATTRIBUTE.\n", name);
  286.         exit(1);
  287.     }
  288.  
  289.     for (i=0; i<idcnt; i++)
  290.         if (strcmp(ids[i].name, name) == 0)
  291.             if ((type & METHOD) || done){
  292.                 printf("Error: Redefinition of %s.\n", name);
  293.                 exit(1);
  294.             } else
  295.                 done = TRUE;
  296.  
  297.     if (!done){
  298.         strcpy(ids[idcnt].name, name);
  299.         ids[idcnt].type = type;
  300.         ids[idcnt].value = value;
  301.  
  302.         if (++idcnt > NOOFIDS){
  303.             printf("Error: Too many IDs. Maximum: %d.\n", NOOFIDS);
  304.             exit(1);
  305.         }
  306.     }
  307. }
  308.  
  309. void MakePublic(void)
  310. {
  311.     if (idcnt>0)
  312.         ids[idcnt-1].type |= PUBLIC;
  313. }
  314.  
  315. void OutputIDs(FILE *fp, FILE *fpp, char type, long base, char *basename)
  316. {
  317.     int i;
  318.  
  319.     for (i=0; i<idcnt; i++)
  320.         if ((ids[i].type & type) && (strncmp(basename, ids[i].name, strlen(basename)) == 0))
  321.             if (ids[i].type & PUBLIC)
  322.                 fprintf(fp, "#define %s\t\t0x%p\n", ids[i].name, ids[i].value + base);
  323.             else
  324.                 fprintf(fpp, "#define %s\t\t0x%p\n", ids[i].name, ids[i].value + base);
  325.  
  326. }
  327.  
  328. void MakeMainHeader(FILE *fp, char *headerfilename, char *privheaderfilename)
  329. {
  330.     struct tm *tp;
  331.     long t;
  332.  
  333.     time(&t);
  334.     tp = localtime(&t);
  335.  
  336.     fprintf(fp,messages[HEADER],"Implementation",clsname,asctime(tp));
  337.     fprintf(fp,"\n#include %c%s%c\n#include %c%s%c\n",'"',headerfilename,'"','"',privheaderfilename,'"');
  338. }
  339.  
  340. void MakeHeaders(char *headerfilename, char *privheaderfilename, long base)
  341. {
  342.     FILE *fp, *fppriv;
  343.     struct tm *tp;
  344.     long t;
  345.  
  346.     if (!(fp = fopen(headerfilename, "w"))){
  347.         printf(messages[ERROPENW], headerfilename);
  348.         exit(1);
  349.     }
  350.  
  351.     if (!(fppriv = fopen(privheaderfilename, "w"))){
  352.         printf(messages[ERROPENW], privheaderfilename);
  353.         exit(1);
  354.     }
  355.  
  356.     time(&t);
  357.     tp = localtime(&t);
  358.  
  359.     fprintf(fp,messages[HEADER],"Header",clsname,asctime(tp));
  360.     fprintf(fp,messages[CONSTRUCTOR_HEADER],clsname,";");
  361.     fprintf(fp,"\n\n/* PUBLIC METHODS */\n");
  362.  
  363.     fprintf(fppriv,messages[HEADER],"Private header",clsname,asctime(tp));
  364.     fprintf(fppriv,"\n\n/* PRIVATE METHODS */\n");
  365.  
  366.     OutputIDs(fp, fppriv, METHOD, base, methodbase);
  367.  
  368.     fprintf(fp,"\n\n/* PUBLIC ATTRIBUTES */\n");
  369.  
  370.     fprintf(fppriv,"\n\n/* PRIVATE ATTRIBUTES */\n");
  371.  
  372.     OutputIDs(fp, fppriv, ATTRIBUTE, base + mthcnt, attributebase);
  373.  
  374.     fclose(fp);
  375.     fclose(fppriv);
  376. }
  377.  
  378. void MakeHousekeeping(FILE *fp)
  379. {
  380.     int i;
  381.  
  382.     fprintf(fp,messages[DISPATCH_HEADER],clsname);
  383.  
  384.     for (i=0; i<idcnt; i++)
  385.         if (ids[i].type & METHOD)
  386.             fprintf(fp,messages[DISPATCH_CASE],ids[i].name,clsname,ids[i].name);
  387.  
  388.     fprintf(fp,messages[DISPATCH_TRAILER]);
  389.  
  390.     fprintf(fp,messages[CONSTRUCTOR_HEADER],clsname,"\n{\n");
  391.     fprintf(fp,messages[CONSTRUCTOR_BODY], superclsname, dataname, clsname);
  392. }
  393.